import java.util.PriorityQueue;
import java.util.Timer;

//通过这个类描述一个任务
class MyTimerTask implements Comparable<MyTimerTask>{
    //要有一个要执行的任务
    private Runnable runnable;
    //还有一个执行任务的时间
    private long time;

    public MyTimerTask(Runnable runnable, long delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time - o.time);
    }

    public Runnable getRunnable() {
        return runnable;
    }

    public long getTime() {
        return time;
    }
}

//实现定时器
class MyTimer{
    //使用一个数据结构, 保存所有要安排的任务
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
    //锁对象
    private Object locker = new Object();

    public void schedule(Runnable runnable, long delay){
        synchronized (locker){
            queue.offer(new MyTimerTask(runnable, delay));
            locker.notify();
        }
    }

    //扫描线程
    public MyTimer(){
        Thread t = new Thread(() -> {
           while (true)
           {
               try {
                   synchronized (locker) {
                       //不要使用if作为wait的判定条, 应该使用while
                       //使用while的目的是为了在wait被唤醒的时候, 再次确认一下条件
                       while (queue.isEmpty()) {
                           //使用wait进行等待
                           //这里的wait需要由另外的线程唤醒
                           //添加了新任务, 就应该唤醒
                           locker.wait();
                       }

                       MyTimerTask task = queue.peek();
                       //比较一下看当前的队首元素是否可以执行了
                       long curTime = System.currentTimeMillis();
                       if (curTime >= task.getTime()) {
                           //当前时间已经达到了任务时间, 就可以执行任务了
                           task.getRunnable().run();
                           ;
                           //任务执行完, 就可以从队列中删除
                           queue.poll();
                       } else {
                           //当前时间还没到任务时间, 暂时不执行任务
                           //暂时先啥都不干, 等待下一轮的循环判定
                           locker.wait(task.getTime() - curTime);
                       }
                   }
               }
               catch(InterruptedException e)
               {
                    e.printStackTrace();
               }
           }
        });
        t.start();
    }
}
public class Demo26 {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("3000");
            }
        },3000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("2000");
            }
        },2000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("1000");
            }
        },1000);
        System.out.println("程序开始执行!");
    }
}
